/**
 * 
 */
package halton;

import org.apache.log4j.Logger;

import umontreal.iro.lecuyer.hups.PointSet;
import umontreal.iro.lecuyer.hups.RadicalInverse;

/**
 * @author Propriétaire
 * 
 */
public class Halton extends PointSet {
	
	public static Logger	LOG	= Logger.getLogger(Halton.class);
	
	public Halton(int n, int dim) {
		
		LOG.info("create a Halton sequence of " + n + " points and " + dim + " dimentions");
		
		if (dim < 1) {
			LOG.error("create a Halton sequence of " + n + " points and " + dim + " dimentions");
			throw new IllegalArgumentException("Halton sequence must have positive dimension dim");
		} else {
			this.dim = dim;
			numPoints = n;
			base = RadicalInverse.getPrimes(dim);
			return;
		}
	}
	
	public void init(double x0[]) {
		radinv = new RadicalInverse[dim];
		for (int i = 0; i < dim; i++)
			radinv[i] = new RadicalInverse(base[i], x0[i]);
		
	}
	
	public void addFaurePermutations() {
		permutation = new int[dim][];
		for (int i = 0; i < dim; i++) {
			permutation[i] = new int[base[i]];
			RadicalInverse.getFaurePermutation(base[i], permutation[i]);
		}
		
		permuted = true;
	}
	
	public void ErasePermutations() {
		permuted = false;
		permutation = (int[][]) null;
	}
	
	public int getNumPoints() {
		return numPoints;
	}
	
	public double getCoordinate(int i, int j) {
		if (radinv != null)
			if (!permuted)
				return radinv[j].nextRadicalInverse();
			else
				throw new UnsupportedOperationException(
				        "Fast radical inverse is not implemented in case of permutation");
		if (permuted)
			return RadicalInverse.permutedRadicalInverse(base[j], permutation[j], i);
		else
			return RadicalInverse.radicalInverse(base[j], i);
	}
	
	private int	           base[];
	
	private int	           permutation[][];
	
	private boolean	       permuted;
	
	private RadicalInverse	radinv[];
}
